<?php
/**
* PXFSQLBuilder
*
*/
class PXFSQLBuilder
{

	public static function select($table,$fields)
	{
		$fields = PXFSQLBuilder::prepareFields($fields,$table);
		$query = sprintf('SELECT %s FROM `%s` ',$fields,$table->__toString());
		return $query;
	}

	public static function count($table)
	{
		$query = sprintf('SELECT count(*) as `total` FROM `%s` ',$table->__toString());
		return $query;
	}

	public static function whereByConditions(PXFCondition $conditions)
	{
		return sprintf(' WHERE %s',$conditions->__toString());
	}

	public static function innerJoin($table,$table2,$id,$args)
	{		
		$join = PXFSQLBuilder::joinTables($table,$table2);
		$query = sprintf('INNER JOIN %s on %s.id = %s.%s_id',$join,$table,$join,$table);
		$condition = null;
		if(array_key_exists('condition',$args))
		{
			$args['condition']->add(PXFCondition::opAND(sprintf('%s.%s_id',$join,$table2),$id));
		}
		else
		{
			$args['condition'] = new PXFCondition(sprintf('%s.%s_id',$join,$table2),$id);
		}
		$query .= PXFSQLBuilder::parseArgs($args);
		return $query;
	}

	public static function joinTables($table,$table2)
	{
		$tables = array(sprintf('%s',$table),sprintf('%s',$table2));
		sort($tables);
		$join = join('_',$tables);
		return $join;
	}

	public static function prepareFields($fields,$table)
	{
		$output = array();
		foreach($fields as $field)
		{
			$output[] = sprintf('`%s` as `%s_%s`',$field,$table->__toString(),$field);
		}
		return join(',',$output);
	}

	public static function undoPrepareFields($model,$fields)
	{
		foreach($model->getFields() as $field)
		{
			$output[$field] = $fields[sprintf('%s_%s',$model->__toString(),$field)];
		}
		return $output;
	}
	
	public static function insert($table,$fields)
	{
		$tfields = array();
		$values = array();
		foreach ($fields as $key => $value)
		{
			$tfields[] = sprintf('`%s`',$key);
			$values[] = ($key != 'id') ? sprintf('"%s"',$value) : $value;
		}
		return sprintf('INSERT INTO `%s` (%s) VALUES (%s)',$table->__toString(),join(',',$tfields),join(',',$values));
	}
	
	public static function replace($table,$fields)
	{
		$tfields = array();
		$values = array();
		foreach ($fields as $key => $value)
		{
			$tfields[] =sprintf('`%s`',$key);
			$values[] = ($key != 'id') ? sprintf('"%s"',$value) : $value;
		}
		return sprintf('REPLACE INTO `%s` (%s) VALUES (%s)',is_object($table) ? $table->__toString() : $table,join(',',$tfields),join(',',$values));
	}

	public static function delete($table)
	{
		$query = sprintf('DELETE FROM `%s` ',is_object($table) ? $table->__toString() : $table);
		return $query;
	}

	public static function update($table,$fields)
	{
		$update = array();
		foreach ($fields as $key => $value)
		{
			$update[] = sprintf('`%s` = "%s"',$key,$value);
		}
		$update = join(',',$update);
		return sprintf('UPDATE `%s` SET %s ',$table->__toString(),$update);
	}

	public static function parseArgs($args)
	{
		$limit = $order = $condition = '';
		if(array_key_exists('limit',$args))
		{
			$limit = new PXFLimit($args['limit'][0],$args['limit'][1]);
		}

		if(array_key_exists('order',$args))
		{
			if(is_array($args['order']))
			{
				$order = new PXFOrderBy($args['order'][0]);
				if(count($args['order']) > 1)
				{
					for($x = 1; $x < count($args['order']); $x++)
					{
						$order->add($args['order'][$x]);
					}
				}
			}
		}

		if(array_key_exists('order_desc',$args))
		{
			if(is_array($args['order_desc']))
			{
				$order = new PXFOrderBy($args['order_desc'][0]);
				if(count($args['order_desc']) > 1)
				{
					for($x = 1; $x < count($args['order_desc']); $x++)
					{
						$order->add($args['order_desc'][$x]);
					}
				}
				$order->desc();
			}
		}

		if(array_key_exists('condition',$args))
		{
			$condition = PXFSQLBuilder::whereByConditions($args['condition']);
		}
		return sprintf('%s %s %s',
										is_object($condition) ? $condition->__toString() : $condition,
										is_object($order)     ? $order->__toString() : $order,
										is_object($limit)     ? $limit->__toString() : $limit
										); 
	}
}

class PXFLimit
{
	private $from;
	private $to;
	public function __construct($from,$to)
	{
		$this->from = $from;
		$this->to = $to;
	}
	
	public function __toString()
	{
		return sprintf(' LIMIT %s,%s ',$this->from,$this->to);
	}
}

class PXFOrderBy
{
	private $desc = false;

	public function __construct($field)
	{
		$this->order_by = sprintf('ORDER BY (%s',$field);
	}

	public function add($field)
	{
		$this->order_by .= sprintf(',%s',$field);
	}

	public function desc()
	{
		$this->desc = true;
	}
	
	public function __toString()
	{
		return sprintf('%s) %s',$this->order_by,$this->desc ? 'DESC' : '');
	}
}

class PXFCondition
{
	private $query = '';

	public function __construct($field,$value,$operator = '=')
	{
		$this->query = sprintf('(%s %s %s)',$field,$operator,
						get_class($value) ? $value : sprintf('"%s"',$value));
	}

	public function add($opt)
	{
		$this->query .= $opt;
	}
	
	public static function opAND($field,$value,$operator = '=')
	{
		return sprintf(' AND (%s %s %s)',$field,$operator,
						get_class($value) ? $value : sprintf('"%s"',$value));
	}

	public static function opOR($field,$value,$operator = '=')
	{
		return sprintf(' OR (%s %s %s)',$field,$operator,$value);
	}

	public function __toString()
	{
		return sprintf('(%s)',$this->query);
	}
}

class PXFField 
{
	private $name;
	private $type;
	private $value;

	public function __construct($name,$type,$value)
	{
	}

	public function __toString()
	{
		return $this->name;
	}

	public function escape()
	{
		return sprintf('"%s"',$this->value);
	}
}

?>
